/**
 * Created by Administrator on 2017/1/16.
 */

var MJPlayer = require('../MJ/player').MJPlayer;
var MJ = require('../MJ/MJ');
var Const = require('./const');
var SubCode = require('../subCode');

exports.JLMJPlayer = MJPlayer.extend({
    _selectPiao: 0,
    _gangTasks: [],

    init: function(uid, msg) {
        this._super(uid, msg);

        this._stat.zmCount = 0;             // 自摸次数
        this._stat.dpCount = 0;             // 点炮次数
        this._stat.dhCount = 0;             // 点胡次数
        this._stat.anGangCount = 0;        // 暗杠次数
        this._stat.mingGangCount = 0;      // 明杠次数
        this._stat.lzCount = 0;             // 庄家次数
        this._stat.roundRules = {};
        this._stat.roundPiaoScore = 0;     // 飘分

        this._selectPiao = -1;               // 选择飘 -1/0/1 未选择/不飘/飘
        this._gangTasks = [];                // 仅仅是用来记录杠牌顺序的
    },

    isPiao: function() {
        return this._selectPiao == 1;
    },

    setPiao: function(piao) {
        this._selectPiao = (piao) ? 1 : 0;
    },

    isPiaoSelected: function() {
        return this._selectPiao != -1;
    },

    settlementGangScore: function() {
        var player = this;
        var room = this.getRoom();
        var roomRule = room.getOption("RULE");

        var totalGangScore = 0;
        for (var i = 0, l = this._gangCards.length; i < l; ++i) {
            var gangInfo = this._gangCards[i];
            //if (gangInfo.overdue || gangInfo.unscored) {
            //    continue;
            //}

            if (gangInfo.type) {
                var score = Const.SpecGangScore[gangInfo.type] || 0;
                if (gangInfo.buCards) {
                    score += gangInfo.buCards.length * 2;
                    if (gangInfo.unscored) {
                        score -= 2;
                    }
                }
                totalGangScore += score;
            } else {
                //if (gangInfo.overdue || gangInfo.unscored) {
                //    continue;
                //}
                if (gangInfo.unscored) {
                    continue;
                }

                var score = Const.GangScore[gangInfo.gang] || 0;
                if (gangInfo.card == MJ.Value.TONG1 || gangInfo.card == MJ.Value.TIAO1 || gangInfo.card == MJ.Value.WAN1) {
                    score *= 2;
                }
                totalGangScore += score;
            }
        }

        if (player.getRoundResult() == MJ.Result.ZM && (Const.OptionRule.XFG == roomRule || Const.OptionRule.XJFD == roomRule)) {
            var huCard = player.getRoundHuCard();
            if (huCard == MJ.ZI.HZ || huCard == MJ.ZI.FC || huCard == MJ.ZI.BB) {
                if (this._isHuZFB(player.getRoundHuCards())) {
                    totalGangScore += 2;
                }
            }
        }

        // 点炮包自己模式下，所有杠分结算时除2（减半）
        if (room.getOption("DPQB") == 3) {
            totalGangScore = Math.round(totalGangScore*0.5);
        }

        // 向其它人收取杠分
        room.enumPlayers(function(eIndex, ePlayer) {
            if (eIndex != player.getIndex()) {
                player.addRoundGangScore(totalGangScore);
                ePlayer.addRoundGangScore(-totalGangScore);
            }
        });
    },

    settlementPatternScore: function() {
        if (!this.isRoundHu()) {
            return;
        }

        var player = this;
        var room = this.getRoom();
        var dpPlayer = room.getPlayerByIndex(room.getFirstDPIndex());

        // 结算牌型及基础分
        var basicFan = this._stat.roundPatternScore + ExObject.sumValue(this._stat.roundItemScores);
        var maxFan = room.getOption("FAN");

        var piaoScore = room.getOption("PIAO");
        var DPQB = room.getOption("DPQB");

        if (DPQB == 3) { //点炮包自己模式下，飘分原4分变为3分
            piaoScore = Math.round(piaoScore*0.75);
        }

        // 结算每个人的分数
        if (DPQB == 1) {
            room.enumPlayers(function(eIndex, ePlayer) {
                if (eIndex == player.getIndex()) {
                    return;
                }

                var fan = Math.min(maxFan, basicFan + ExObject.sumValue(ePlayer._stat.roundItemScores));
                var score = Math.pow(2, fan);

                ePlayer.addRoundScore(-score);
                player.addRoundScore(score);

                if (player.isPiao()) {
                    player._stat.roundPiaoScore += piaoScore;
                    ePlayer._stat.roundPiaoScore -= piaoScore;
                }

                if (ePlayer.isPiao()) {
                    player._stat.roundPiaoScore += piaoScore;
                    ePlayer._stat.roundPiaoScore -= piaoScore;
                }
            });
        } else if (DPQB == 2) {
            room.enumPlayers(function(eIndex, ePlayer) {
                if (eIndex == player.getIndex()) {
                    return;
                }

                var fan = Math.min(maxFan, basicFan + ExObject.sumValue(ePlayer._stat.roundItemScores));
                var score = Math.pow(2, fan);

                if (dpPlayer && !dpPlayer.isBaoTing()) { // 点炮包三家分由点炮者支付
                    dpPlayer.addRoundScore(-score);
                } else {
                    ePlayer.addRoundScore(-score);
                }
                player.addRoundScore(score);

                if (player.isPiao()) {
                    player._stat.roundPiaoScore += piaoScore;
                    ePlayer._stat.roundPiaoScore -= piaoScore;
                }

                if (ePlayer.isPiao()) {
                    player._stat.roundPiaoScore += piaoScore;
                    ePlayer._stat.roundPiaoScore -= piaoScore;
                }
            });
        } else if (DPQB == 3) {
            this._stat.roundTarget.forEach(function(playerIndex) {
                var ePlayer = room.getPlayerByIndex(playerIndex);
                if (ePlayer) {
                    var fan = Math.min(maxFan, basicFan + ExObject.sumValue(ePlayer._stat.roundItemScores));
                    var score = Math.pow(2, fan);

                    ePlayer.addRoundScore(-score);
                    player.addRoundScore(score);

                    if (player.isPiao()) {
                        player._stat.roundPiaoScore += piaoScore;
                        ePlayer._stat.roundPiaoScore -= piaoScore;
                    }

                    if (ePlayer.isPiao()) {
                        player._stat.roundPiaoScore += piaoScore;
                        ePlayer._stat.roundPiaoScore -= piaoScore;
                    }
                }
            });
        }
    },

    settlementRules: function() {
        var rules = this._stat.roundRules;
        var room = this.getRoom();
        var player = this;

        var existKaiMenGang = false;
        var existMenQingGang = false;
        var existSpecGang = false;
        this._gangCards.forEach(function (gangInfo) {
            if (gangInfo.type) {
                existSpecGang = true;
                existMenQingGang = true;
            } else {
                if (gangInfo.gang == MJ.Gang.AN || gangInfo.gang == MJ.Gang.ANS) {
                    existMenQingGang = true;
                } else {
                    existKaiMenGang = true;
                }
            }
        });

        var isSpecHu = (player.getRoundPattern() == Const.Pattern.PAIR7 || player.getRoundPattern() == Const.Pattern.ONE13);

        // 判断 门清
        if (!player.isRoundHu() || !isSpecHu) {
            if (this._chiCards.length == 0 && this._pengCards.length == 0 && !existKaiMenGang) {
                rules[Const.ScoreRule.MenQing] = 1;
            }
        }

        // 判断 手把一
        if (Object.keys(this._handCards.getCards()).length == 1 && !existMenQingGang) {
            rules[Const.ScoreRule.ShouBaYi] = 1;
        }

        // 判断 四归一/一般高 (明)
        var mingCards = {};
        var lianCards = {};
        this._pengCards.forEach(function(card) {
            ExObject.addNumber(mingCards, card, 3);
        });
        this._chiCards.forEach(function(chiInfo) {
            var card = chiInfo.selectCard;
            ExObject.addNumber(lianCards, card, 1);
            ExObject.addNumber(mingCards, card, 1);
            ExObject.addNumber(mingCards, card - 1, 1);
            ExObject.addNumber(mingCards, card - 2, 1);
        });

        if (!isSpecHu) {
            var siGuiYiCount = 0;
            ExObject.each(mingCards, function(c, n) {
                if (n == 4) {
                    siGuiYiCount++;
                }
            });

            if (siGuiYiCount > 0) {
                rules[Const.ScoreRule.SiGuiYi] = siGuiYiCount;
            }

            if (ExObject.existGTE(lianCards, 2)) {
                rules[Const.ScoreRule.YiBanGao] = 1;
            }
        }


        //以下规则只针对赢家有效
        if (!this.isRoundHu()) {
            return;
        }

        var huCard = this.getRoundHuCard();
        var cards = this.getRoundHuCards();
        var ziCards = MJ.getColorCards(cards, MJ.Color.ZI);
        var roomRule = room.getOption("RULE");

        // 判断 清一色/混一色
        var colors = this.getColorsWithCards(cards);
        if (colors.length == 1) {
            if (existSpecGang) {
                rules[Const.ScoreRule.HunYiSe] = 1;
            } else {
                rules[Const.ScoreRule.QingYiSe] = 1;
            }
        } else if (colors.length == 2) {
            if (colors.indexOf(MJ.Color.ZI) != -1) {
                rules[Const.ScoreRule.HunYiSe] = 1;
            }
        }

        // 特殊胡牌 不可能有后面的规则
        if (isSpecHu) {
            return;
        }

        // 判断 四归一
        var allCards = clone(mingCards);
        ExObject.each(cards, function(card, num) {
            ExObject.addNumber(allCards, card, num);
        });

        if (Const.OptionRule.XFG == roomRule || Const.OptionRule.XJFD == roomRule) {
            this._gangCards.forEach(function(gangInfo) {
                if (gangInfo.type) {
                    gangInfo.cards.forEach(function(card) {
                        ExObject.addNumber(allCards, card, 1);
                    });
                }
            });
        }

        var siGuiYiCount = 0;
        ExObject.each(allCards, function(c, n) {
            if (n == 4) {
                siGuiYiCount++;
            }
        });

        if (siGuiYiCount > 0) {
            //ExObject.addNumber(rules, Const.ScoreRule.SiGuiYi, siGuiYiCount);
            rules[Const.ScoreRule.SiGuiYi] = siGuiYiCount;
        }

        // 判断 一般高
        if (!rules[Const.ScoreRule.YiBanGao]) {
            colors.forEach(function(color) {
                if (MJ.isBasicColor(color)) {
                    var splitResults = MJ.splitColorCards(MJ.getValue(color, 1), MJ.getValue(color, MJ.COLOR_CARD_NUM), MJ.getColorCards(cards, color));
                    splitResults.forEach(function(result) {
                        var allLianCards = clone(lianCards);
                        result.forEach(function(item) {
                            if (item.length == 3 && item[0] != item[2]) {
                                ExObject.addNumber(allLianCards, item[2], 1);
                            }
                        })

                        if (ExObject.existGTE(allLianCards, 2)) {
                            rules[Const.ScoreRule.YiBanGao] = 1;
                        }
                    });
                }
            });
        }

        if (!rules[Const.ScoreRule.YiBanGao] && (Const.OptionRule.XFG == roomRule || Const.OptionRule.XJFD == roomRule)) {
            var tmpZiCards = clone(ziCards);
            var huZFBCount = 0;
            while (this._isHuZFB(tmpZiCards)) {
                huZFBCount++;
                [MJ.ZI.HZ, MJ.ZI.FC, MJ.ZI.BB].forEach(function(card) {
                    MJ.delCard(tmpZiCards, card, 1);
                });
            }
            if (this._getSpecGang(Const.SpecGang.XI)) {
                huZFBCount++;
            }

            if (huZFBCount >= 2) {
                rules[Const.ScoreRule.YiBanGao] = 1;
            }
        }

        // 判断夹胡
        if (player.isBaoTing() || room.getOption("TING")) { // 报听后不计算夹胡
            return;
        }

        var isJiaHu = false;
        if (player.getTingCards().length == 1) { // 唯一胡牌都算夹胡
            isJiaHu = true;
        }

        if (!isJiaHu) {
            var huColor = MJ.getColor(huCard);

            if (MJ.isBasicColor(huColor)) {
                var huPoint = MJ.getPoint(huCard);
                var huColorMinCard = MJ.getValue(huColor, 1);
                var huColorMaxCard = MJ.getValue(huColor, MJ.COLOR_CARD_NUM);
                var huColorCards = MJ.getSectionCards(cards, huColorMinCard, huColorMaxCard);

                var colorSplits = MJ.splitColorCards(huColorMinCard, huColorMaxCard, huColorCards);
                colorSplits.forEach(function(items) {
                    items.forEach(function(item) {
                        if (isJiaHu) {
                            return;
                        }

                        if (item.length == 2) {
                            if (item[0] == huCard) {
                                if (huColorCards[huCard] == 2) { //单调将
                                    var otherJiangCards = [];
                                    for (var tmpCard = huColorMinCard; tmpCard <= huColorMaxCard; ++tmpCard) {
                                        if (tmpCard != huCard && huColorCards[tmpCard] > 0) {
                                            var tmpColorCards = clone(huColorCards);
                                            MJ.delCard(tmpColorCards, huCard, 1);
                                            MJ.delCard(tmpColorCards, tmpCard, 1);
                                            if (MJ.checkHuColorCards(huColorMinCard, huColorMaxCard, tmpColorCards)) {
                                                otherJiangCards.push(tmpCard);
                                            }
                                        }
                                    }
                                    if (otherJiangCards.length == 0) {
                                        isJiaHu = true;
                                    }
                                }
                            }
                        } else if (item.length == 3) {
                            if (item[0] != item[1]) { //不是三张一样的牌
                                if (huPoint == 3 && huCard == item[2]) { //边胡3
                                    isJiaHu = true;
                                }

                                if (huPoint == 7 && huCard == item[0]) { //边胡7
                                    isJiaHu = true;
                                }

                                if (huCard == item[1]) { //夹张
                                    isJiaHu = true;
                                }
                            }
                        }
                    });
                });
            } else if (huCard >= MJ.ZI.HZ && huCard <= MJ.ZI.BB) {
                var huColorCards = MJ.getSectionCards(cards, MJ.ZI.HZ, MJ.ZI.BB);
                var colorSplits = MJ.splitColorCards(MJ.ZI.HZ, MJ.ZI.BB, huColorCards);
                colorSplits.forEach(function(items) {
                    items.forEach(function(item) {
                        if (isJiaHu) {
                            return;
                        }

                        if (item.length == 2) {
                            if (item[0] == huCard) {
                                var otherJiangCards = [];
                                for (var tmpCard = MJ.ZI.HZ; tmpCard <= MJ.ZI.BB; ++tmpCard) {
                                    if (tmpCard != huCard) {
                                        var tmpColorCards = clone(huColorCards);
                                        MJ.delCard(tmpColorCards, huCard, 1);
                                        MJ.addCard(tmpColorCards, tmpCard, 1);
                                        if (MJ.checkHuColorCards(huColorMinCard, huColorMaxCard, tmpColorCards)) {
                                            otherJiangCards.push(tmpCard);
                                        }
                                    }
                                }
                                if (otherJiangCards.length == 0) {
                                    isJiaHu = true;
                                }
                            }
                        } else if (item.length == 3) {
                            if (item[0] != item[1]) { //不是三张一样的牌
                                isJiaHu = true;
                            }
                        }
                    });
                });
            }
        }

        if (isJiaHu) {
            rules[Const.ScoreRule.JiaHu] = 1;
        }
    },

    settlement: function() {
        this._super();

        this.addRoundScore(this._stat.roundGangScore);
        this.addRoundScore(this._stat.roundPiaoScore);

        if (this._stat.roundResult == MJ.Result.ZM) {
            this._stat.zmCount++;
        } else if (this._stat.roundResult == MJ.Result.DH) {
            this._stat.dhCount++;
            if (this._stat.roundTarget.length > 0) {
                var dpPlayer = this.getRoom().getPlayerByIndex(this._stat.roundTarget[0]);
                if (dpPlayer) {
                    dpPlayer._stat.dpCount++;
                }
            }
        }

        for (var i = 0, l = this._gangCards.length; i < l; ++i) {
            var gangInfo = this._gangCards[i];
            if (gangInfo.type) {

            } else {
                if (gangInfo.gang == MJ.Gang.AN || gangInfo.gang == MJ.Gang.ANS) {
                    this._stat.anGangCount++;
                } else {
                    this._stat.mingGangCount++;
                }
            }
        }

        if (this.isDealer()) {
            this._stat.lzCount++;
        }
    },

    /******************************************************************
     * 重载的接口
     ******************************************************************/

    getReconnectInfo: function(isSelf) {
        var info = this._super(isSelf);
        info.selectPiao = this._selectPiao;
        return info;
    },

    getSettlementInfo: function() {
        var info = this._super();
        info.gangCards = this._gangCards;
        info.pengCards = this._pengCards;
        info.chiCards = this._chiCards;
        info.handCards = this._handCards.getCards();
        return info;
    },

    onStartNewRound: function() {
        this._super();
        this._selectPiao = -1;
        this._stat.roundRules = {};
        this._stat.roundPiaoScore = 0;
        this._gangTasks = [];
    },

    //getInitHandCardPreCards: function() {
    //    var preCards = [];
    //
    //    var distance = this.getRoom().getIndexDistance(this.getRoom().getDealerIndex(), this.getIndex());
    //    if (distance == 0) {
    //        preCards.push(MJ.getValue(MJ.Color.TONG, 5));
    //        preCards.push(MJ.getValue(MJ.Color.TONG, 6));
    //        preCards.push(MJ.getValue(MJ.Color.TONG, 7));
    //
    //        preCards.push(MJ.getValue(MJ.Color.TONG, 7));
    //        preCards.push(MJ.getValue(MJ.Color.TONG, 8));
    //        preCards.push(MJ.getValue(MJ.Color.TONG, 9));
    //
    //        preCards.push(MJ.getValue(MJ.Color.TIAO, 1));
    //        preCards.push(MJ.getValue(MJ.Color.TIAO, 1));
    //        preCards.push(MJ.getValue(MJ.Color.TIAO, 1));
    //
    //        preCards.push(MJ.getValue(MJ.Color.TIAO, 7));
    //        preCards.push(MJ.getValue(MJ.Color.TIAO, 8));
    //        preCards.push(MJ.getValue(MJ.Color.TIAO, 9));
    //        preCards.push(MJ.getValue(MJ.Color.TIAO, 9));
    //
    //        preCards.push(MJ.ZI.BF);
    //
    //    } else if (distance == 1) {
    //        preCards.push(MJ.getValue(MJ.Color.WAN, 1));
    //        preCards.push(MJ.getValue(MJ.Color.WAN, 1));
    //        preCards.push(MJ.getValue(MJ.Color.WAN, 1));
    //
    //        preCards.push(MJ.getValue(MJ.Color.WAN, 2));
    //        preCards.push(MJ.getValue(MJ.Color.WAN, 2));
    //        preCards.push(MJ.getValue(MJ.Color.WAN, 2));
    //
    //        preCards.push(MJ.getValue(MJ.Color.WAN, 3));
    //        preCards.push(MJ.getValue(MJ.Color.WAN, 3));
    //
    //        preCards.push(MJ.ZI.DF);
    //        preCards.push(MJ.ZI.NF);
    //        preCards.push(MJ.ZI.XF);
    //        preCards.push(MJ.ZI.BF);
    //    } else {
    //
    //    }
    //
    //    return preCards;
    //},

    // 重写检查杠的逻辑
    checkGang: function() {
        var gangArray = this._super();

        var room = this.getRoom();
        var handCards = this._handCards.getCards();
        var isFirstHand = this._playCards.length == 0;

        if (Const.OptionRule.XFG == room.getOption("RULE")) {
            if (!this._getSpecGang(Const.SpecGang.SF)) {
                if (MJ.existCard(handCards, MJ.ZI.DF) &&
                    MJ.existCard(handCards, MJ.ZI.NF) &&
                    MJ.existCard(handCards, MJ.ZI.XF) &&
                    MJ.existCard(handCards, MJ.ZI.BF)) {
                    gangArray.push({type: Const.SpecGang.SF, cards:[MJ.ZI.DF, MJ.ZI.NF, MJ.ZI.XF, MJ.ZI.BF]});
                }
            }

            if (!this._getSpecGang(Const.SpecGang.XI)) {
                if (MJ.existCard(handCards, MJ.ZI.HZ) &&
                    MJ.existCard(handCards, MJ.ZI.FC) &&
                    MJ.existCard(handCards, MJ.ZI.BB)) {
                    gangArray.push({type: Const.SpecGang.XI, cards:[MJ.ZI.HZ, MJ.ZI.FC, MJ.ZI.BB]});
                }
            }

            this._gangCards.forEach(function(gangInfo) {
                if (gangInfo.type == Const.SpecGang.SF) {
                    if (MJ.existCard(handCards, MJ.ZI.DF)) gangArray.push({type: gangInfo.type, buCard: MJ.ZI.DF});
                    if (MJ.existCard(handCards, MJ.ZI.NF)) gangArray.push({type: gangInfo.type, buCard: MJ.ZI.NF});
                    if (MJ.existCard(handCards, MJ.ZI.XF)) gangArray.push({type: gangInfo.type, buCard: MJ.ZI.XF});
                    if (MJ.existCard(handCards, MJ.ZI.BF)) gangArray.push({type: gangInfo.type, buCard: MJ.ZI.BF});
                } else if (gangInfo.type == Const.SpecGang.XI) {
                    if (MJ.existCard(handCards, MJ.ZI.HZ)) gangArray.push({type: gangInfo.type, buCard: MJ.ZI.HZ});
                    if (MJ.existCard(handCards, MJ.ZI.FC)) gangArray.push({type: gangInfo.type, buCard: MJ.ZI.FC});
                    if (MJ.existCard(handCards, MJ.ZI.BB)) gangArray.push({type: gangInfo.type, buCard: MJ.ZI.BB});
                }
            });
        } else if (Const.OptionRule.XJFD == room.getOption("RULE")) {
            var existTiao1 = handCards[MJ.Value.TIAO1] || 0;
            var usedTiao1 = 0;

            if (!this._getSpecGang(Const.SpecGang.SF)) {
                var sfCards = [];
                if (MJ.existCard(handCards, MJ.ZI.DF)) sfCards.push(MJ.ZI.DF);
                if (MJ.existCard(handCards, MJ.ZI.NF)) sfCards.push(MJ.ZI.NF);
                if (MJ.existCard(handCards, MJ.ZI.XF)) sfCards.push(MJ.ZI.XF);
                if (MJ.existCard(handCards, MJ.ZI.BF)) sfCards.push(MJ.ZI.BF);
                if (sfCards.length == 4) {
                    gangArray.push({type: Const.SpecGang.SF, cards:sfCards});
                } else if (sfCards.length == 3 && isFirstHand && existTiao1) {
                    sfCards.push(MJ.Value.TIAO1);
                    gangArray.push({type: Const.SpecGang.SF, cards:sfCards});
                    usedTiao1 = 1;
                }
            }

            if (!this._getSpecGang(Const.SpecGang.XI)) {
                var xiCards = [];
                if (MJ.existCard(handCards, MJ.ZI.HZ)) xiCards.push(MJ.ZI.HZ);
                if (MJ.existCard(handCards, MJ.ZI.FC)) xiCards.push(MJ.ZI.FC);
                if (MJ.existCard(handCards, MJ.ZI.BB)) xiCards.push(MJ.ZI.BB);
                if (xiCards.length == 3) {
                    gangArray.push({type: Const.SpecGang.XI, cards:xiCards});
                } else if (xiCards.length == 2 && isFirstHand && existTiao1) {
                    xiCards.push(MJ.Value.TIAO1);
                    gangArray.push({type: Const.SpecGang.XI, cards:xiCards});
                    usedTiao1 = 1;
                }
            }

            if (isFirstHand) {
                if (!this._getSpecGang(Const.SpecGang.YD)) {
                    if (MJ.existCard(handCards, MJ.Value.TONG1) &&
                        MJ.existCard(handCards, MJ.Value.TIAO1) &&
                        MJ.existCard(handCards, MJ.Value.WAN1)) {
                        gangArray.push({type: Const.SpecGang.YD, cards:[MJ.Value.TONG1, MJ.Value.TIAO1, MJ.Value.WAN1]});
                    }
                }

                if (!this._getSpecGang(Const.SpecGang.JD)) {
                    var jdCards = [];
                    if (MJ.existCard(handCards, MJ.Value.TONG9)) jdCards.push(MJ.Value.TONG9);
                    if (MJ.existCard(handCards, MJ.Value.TIAO9)) jdCards.push(MJ.Value.TIAO9);
                    if (MJ.existCard(handCards, MJ.Value.WAN9)) jdCards.push(MJ.Value.WAN9);
                    if (jdCards.length == 3) {
                        gangArray.push({type: Const.SpecGang.JD, cards:jdCards});
                    } else if (jdCards.length == 2 && existTiao1) {
                        jdCards.push(MJ.Value.TIAO1);
                        gangArray.push({type: Const.SpecGang.JD, cards:jdCards});
                        usedTiao1 = 1;
                    }
                }
            }

            this._gangCards.forEach(function(gangInfo) {
                if (!gangInfo.type) {
                    return;
                }

                if (gangInfo.type == Const.SpecGang.SF) {
                    if (MJ.existCard(handCards, MJ.ZI.DF)) gangArray.push({type: gangInfo.type, buCard: MJ.ZI.DF});
                    if (MJ.existCard(handCards, MJ.ZI.NF)) gangArray.push({type: gangInfo.type, buCard: MJ.ZI.NF});
                    if (MJ.existCard(handCards, MJ.ZI.XF)) gangArray.push({type: gangInfo.type, buCard: MJ.ZI.XF});
                    if (MJ.existCard(handCards, MJ.ZI.BF)) gangArray.push({type: gangInfo.type, buCard: MJ.ZI.BF});
                    if (existTiao1 > usedTiao1) {
                        gangArray.push({type: gangInfo.type, buCard: MJ.Value.TIAO1});
                        usedTiao1 += 1;
                    }
                } else if (gangInfo.type == Const.SpecGang.XI) {
                    if (MJ.existCard(handCards, MJ.ZI.HZ)) gangArray.push({type: gangInfo.type, buCard: MJ.ZI.HZ});
                    if (MJ.existCard(handCards, MJ.ZI.FC)) gangArray.push({type: gangInfo.type, buCard: MJ.ZI.FC});
                    if (MJ.existCard(handCards, MJ.ZI.BB)) gangArray.push({type: gangInfo.type, buCard: MJ.ZI.BB});
                    if (existTiao1 > usedTiao1) {
                        gangArray.push({type: gangInfo.type, buCard: MJ.Value.TIAO1});
                        usedTiao1 += 1;
                    }
                } else if (gangInfo.type == Const.SpecGang.YD) {
                    if (MJ.existCard(handCards, MJ.Value.TONG1)) gangArray.push({type: gangInfo.type, buCard: MJ.Value.TONG1});
                    if (MJ.existCard(handCards, MJ.Value.TIAO1)) gangArray.push({type: gangInfo.type, buCard: MJ.Value.TIAO1});
                    if (MJ.existCard(handCards, MJ.Value.WAN1)) gangArray.push({type: gangInfo.type, buCard: MJ.Value.WAN1});
                } else if (gangInfo.type == Const.SpecGang.JD) {
                    if (MJ.existCard(handCards, MJ.Value.TONG9)) gangArray.push({type: gangInfo.type, buCard: MJ.Value.TONG9});
                    if (MJ.existCard(handCards, MJ.Value.TIAO9)) gangArray.push({type: gangInfo.type, buCard: MJ.Value.TIAO9});
                    if (MJ.existCard(handCards, MJ.Value.WAN9)) gangArray.push({type: gangInfo.type, buCard: MJ.Value.WAN9});
                    if (existTiao1 > usedTiao1) {
                        gangArray.push({type: gangInfo.type, buCard: MJ.Value.TIAO1});
                        usedTiao1 += 1;
                    }
                }
            }.bind(this));
        }

        var from = this.getIndex();
        gangArray.forEach(function(gangInfo) {
            gangInfo.from = from;
        });

        if (this.isBaoTing()) {
            if (this.nowIsMenQing()) {
                var newGangArray = [];
                gangArray.forEach(function(gangTask) {
                    if (gangTask.type || gangTask.gang == MJ.Gang.AN || gangTask.gang == MJ.Gang.ANS) {
                        newGangArray.push(gangTask); // 不算开门 可以杠
                    }
                });
                gangArray = newGangArray;
            }
        }

        return  gangArray;
    },

    gangCard: function(gangTask) {
        var gangInfo = null;

        if (!gangTask.gangArray) {
            //gangInfo = this._super(gangTask);
        } else {
            var selectGang = gangTask.selectGang || 0;
            if (selectGang > gangTask.gangArray.length) {
                selectGang = 0;
            }

            gangTask = gangTask.gangArray[selectGang];
        }

        if (gangTask.type) {
            gangInfo = this._specGangCard(gangTask);
        } else {
            gangInfo = this._super(gangTask);
        }

        if (gangInfo) {
            this._gangTasks.push(gangTask);
        }

        return gangInfo;
    },

    getLastGang: function() {
        var gangIndex = this._gangTasks.length - 1;

        if (gangIndex < 0) {
            return;
        }

        var gangTask = this._gangTasks[gangIndex];

        if (gangTask.type) {
            return this._getSpecGang(gangTask.type);
        } else {
            var gangCount = this._gangCards.length;
            return (gangCount > 0) ? this._gangCards[gangCount - 1] : null;
        }
    },

    _getSpecGang: function(type) {
        var result = null;
        for (var i = 0, l = this._gangCards.length; i < l; ++i) {
            var gangInfo = this._gangCards[i];
            if (gangInfo.type == type) {
                result = gangInfo;
                break;
            }
        }
        return result;
    },

    _specGangCard: function(gangTask) {
        var gangInfo = null;
        var self = this;

        if (gangTask.buCard) {
            gangInfo = this._getSpecGang(gangTask.type);
            if (gangInfo) {
                if (!gangInfo.buCards) {
                    gangInfo.buCards = [];
                }

                var buCard = gangTask.buCard;
                if (this._handCards.getCardNum(buCard) > 0) {
                    this._handCards.delCard(buCard);
                    gangInfo.buCards.push(buCard);
                }

                gangInfo.buCard = gangTask.buCard;
            }
        } else if (gangTask.cards) {
            gangTask.cards.forEach(function(card) {
                this._handCards.delCard(card);
            }.bind(this));

            gangInfo = clone(gangTask);
            delete gangInfo.playerIndex;
            this._gangCards.push(gangInfo);
        }

        return gangInfo;
    },

    _cancelSpecGang: function(gangTask) {
        var gangIndex = -1;
        for (var i = 0, l = this._gangCards.length; i < l; ++i) {
            var gangInfo = this._gangCards[i];
            if (gangInfo.type == gangTask.type) {
                gangIndex = i; break;
                break;
            }
        }

        if (gangIndex == -1) {
            return;
        }

        var gangInfo = this._gangCards[gangIndex];
        var retGangInfo = clone(gangInfo);
        if (gangTask.buCard) {
            if (gangInfo.buCards.length > 0) {
                this._handCards.addCard(gangTask.buCard, 1);
                gangInfo.buCards.splice(gangInfo.buCards.length - 1, 1);
                gangInfo.buCard = (gangInfo.buCards.length > 0) ? gangInfo.buCards[gangInfo.buCards.length - 1] : 0;
            }
        } else if (gangTask.cards) {
            gangTask.cards.forEach(function(card) {
                this._handCards.addCard(card);
            }.bind(this));

            this._gangCards.splice(gangIndex, 1);
        }
        return retGangInfo;
    },

    _cancelSpecGangForQG: function(gangTask) {
        var gangIndex = -1;
        for (var i = 0, l = this._gangCards.length; i < l; ++i) {
            var gangInfo = this._gangCards[i];
            if (gangInfo.type == gangTask.type) {
                gangIndex = i; break;
                break;
            }
        }

        if (gangIndex == -1) {
            return;
        }

        var gangInfo = this._gangCards[gangIndex];
        var retGangInfo = clone(gangInfo);

        if (gangTask.buCard) {
            if (gangInfo.buCards.length > 0) {
                gangInfo.buCards.splice(gangInfo.buCards.length - 1, 1);
                gangInfo.buCard = (gangInfo.buCards.length > 0) ? gangInfo.buCards[gangInfo.buCards.length - 1] : 0;
            }
        }

        return retGangInfo;
    },

    cancelLastGang: function() {
        var gangIndex = this._gangTasks.length - 1;
        if (gangIndex < 0) {
            return;
        }

        var gangTask = this._gangTasks[gangIndex];

        var gangInfo = (gangTask.type) ? this._cancelSpecGang(gangTask) : this._super();
        if (gangInfo) {
            this._gangTasks.splice(gangIndex, 1);
        }

        return gangInfo;
    },

    cancelLastGangForQG: function(card) {
        var gangIndex = this._gangTasks.length - 1;
        if (gangIndex < 0) {
            return;
        }

        var gangTask = this._gangTasks[gangIndex];

        var gangInfo = null;
        if (gangTask.type) {
            gangInfo = this._cancelSpecGangForQG(gangTask);
            if (gangInfo) {
                this.getRoom().broadcastReplay("onCancelGangForQG", {
                    playerIndex: this.getIndex(),
                    gangInfo: gangInfo,
                });
            }
        } else {
            this._super(card);
        }

        if (gangInfo) {
            this._gangTasks.splice(gangIndex, 1);
        }

        return gangInfo;
    },

    checkChiCondition: function(card) {
        var subConfig = this.getRoom().getSubConfig();
        var color = MJ.getColor(card);
        if (subConfig.colors.indexOf(color) == -1) {
            return false;
        }

        if (!MJ.isBasicColor(color)) {
            return false;
        }

        return true;
    },

    checkHuLogic: function(cards, huCard) {
        var subConfig = this.getRoom().getSubConfig();
        var self = this;
        var room = this.getRoom();

        // 判断13幺
        if (MJ.checkHuOne13(cards)) {
            return Const.Pattern.ONE13;
        }

        var num4 = 0;
        var num3 = 0;
        var num2 = 0;
        var numAll = 0;

        ExObject.each(cards, function(c, n) {
            if (n == 2) {
                num2++;
            } else if (n == 3) {
                num3++;
            } else if (n == 4) {
                num4++;
            }
            numAll += n;
        });

        if ((num2 + num4*2) == 7) { // 七对
            return Const.Pattern.PAIR7;
        }

        if ((num2 == 1) && ((num3*3 + 2) == numAll)) { // 对对胡
            if (this._chiCards.length == 0) {
                return Const.Pattern.PAIR;
            }
        }


        var roomRule = room.getOption("RULE");
        var pattern = MJ.Pattern.NORMAL;


        var exist19 = false; // 是否有19
        var avoid19 = false; // 免19
        var existDX = this._pengCards.length > 0; // 是否有大叉
        var avoidDX = false; // 免大叉

        ExObject.each(cards, function(card, num) {
            if (MJ.getColor(card) == MJ.Color.ZI) {
                avoid19 = true;
            } else {
                var point = MJ.getPoint(card);
                if (point == 1 || point == 9) {
                    exist19 = true;
                }
            }
        });

        this._chiCards.forEach(function(chiInfo) {
            var maxPoint = MJ.getPoint(chiInfo.selectCard);
            if (maxPoint == 9 || maxPoint == 3) {
                exist19 = true;
            }
        });

        this._pengCards.forEach(function(card) {
            if (MJ.getColor(card) == MJ.Color.ZI) {
                avoid19 = true;
            } else {
                var point = MJ.getPoint(card);
                if (point == 1 || point == 9) {
                    exist19 = true;
                }
            }
        });

        this._gangCards.forEach(function(gangInfo) {
            avoidDX = true; //所有杠都免大叉
            if (gangInfo.type) {
                avoid19 = true; //特殊杠免19
            } else {
                var card = gangInfo.card;
                if (MJ.getColor(card) == MJ.Color.ZI) {
                    avoid19 = true;
                } else {
                    var point = MJ.getPoint(card);
                    if (point == 1 || point == 9) {
                        exist19 = true;
                    }
                }
            }
        });

        var color3X2Num = 0; //牌数为3X2的花色
        var colors = subConfig.colors;
        for (var i = 0, l = colors.length; i < l; ++i) {
            var color = colors[i];
            var colorCards = MJ.getColorCards(cards, color);

            var colorCardNum = ExObject.sumValue(colorCards);
            if (colorCardNum == 0) {
                continue;
            }

            if (colorCardNum%3==1) {
                pattern = MJ.Pattern.NONE; break;
            }

            if (colorCardNum%3==2) {
                color3X2Num++;
                if (color3X2Num > 1) {
                    pattern = MJ.Pattern.NONE; break;
                }
            }

            if (MJ.isBasicColor(color)) {
                var splitResults = MJ.splitColorCards(MJ.getValue(color, 1), MJ.getValue(color, MJ.COLOR_CARD_NUM), colorCards);
                if (!splitResults || splitResults.length == 0) {
                    return MJ.Pattern.NONE; break;
                }

                if (!existDX && !avoidDX) {
                    splitResults.forEach(function(splitResult) {
                        splitResult.forEach(function(splitItem) {
                            if (splitItem.length == 3 && (splitItem[0] == splitItem[1])) {
                                existDX = true;
                            }
                        });
                    });
                }
            } else {
                var ziHu = false;  //字牌是否可以胡牌
                if (Const.OptionRule.XFG == roomRule || Const.OptionRule.XJFD == roomRule) {
                    var dnxbCards = {}; // 东南西北
                    var zfbCards = {};  // 中发白

                    ExObject.each(colorCards, function(card, num) {
                        if (card < MJ.ZI.HZ) {
                            dnxbCards[card] = num;
                        } else {
                            zfbCards[card] = num;
                        }
                    });

                    ziHu = MJ.checkPairHuColorCards(dnxbCards) && MJ.checkHuColorCards(MJ.ZI.HZ, MJ.ZI.BB, zfbCards);
                } else {
                    ziHu = MJ.checkPairHuColorCards(colorCards);
                }

                if (!ziHu) {
                    pattern = MJ.Pattern.NONE; break;
                }

                if (!existDX && !avoidDX) {
                    ExObject.each(colorCards, function(card, num) {
                        if (num >= 3) {
                            existDX = true;
                        }
                    });
                }
            }
        }

        if (pattern != Const.Pattern.NORMAL) {
            return pattern;
        }


        // 旋风杠玩法胡中发白免大叉
        if (!avoidDX && (Const.OptionRule.XFG == roomRule || Const.OptionRule.XJFD == roomRule) && this._isHuZFB(cards)) {
            avoidDX = true;
        }

        if ((!exist19 && !avoid19) || (!existDX && !avoidDX)) {
            return MJ.Pattern.NONE;
        }

        // 重新计算对对胡
        num2 = 0;
        num3 = 0;
        numAll = 0;
        ExObject.eachKeyNum(cards, function(c, n) {
            if (c > MJ.COLOR_ZI_NUM) {
                if (n == 2) {
                    num2++;
                } else if (n == 3) {
                    num3++;
                }
                numAll += n;
            }
        });

        if ((num2 == 1) && ((num3*3 + 2) == numAll)) {
            if (this._chiCards.length == 0) {
                pattern = Const.Pattern.PAIR;
            }
        }

        return pattern;
    },

    _existKaiMenGang: function() {
        var exist = false;
        this._gangCards.forEach(function (gangInfo) {
            if (!this.isMenQingGang(gangInfo)) {
                exist = true;
            }
        }.bind(this));
        return exist;
    },

    isMenQingGang: function(gangInfo) {
        return gangInfo.type || gangInfo.gang == MJ.Gang.AN || gangInfo.gang == MJ.Gang.ANS;
    },

    /**
     * 当前是否是门清状态
     * @private
     */
    nowIsMenQing: function() {
        if (this._pengCards.length > 0) {
            return false;
        }

        if (this._chiCards.length > 0) {
            return false;
        }

        var isMenQing = true;
        this._gangCards.forEach(function (gangInfo) {
            if (!this.isMenQingGang(gangInfo)) {
                isMenQing = false;
            }
        }.bind(this));

        return isMenQing;
    },

    /**
     * 是否中发白可以组成胡牌
     * @param cards
     * @returns {boolean}
     * @private
     */
    _isHuZFB: function(cards) {
        var zfbCards = {};
        var zfbCount = 0;
        [MJ.ZI.HZ, MJ.ZI.FC, MJ.ZI.BB].forEach(function(card) {
            var num = cards[card];
            if (num >= 1) {
                zfbCount++;
                zfbCards[card] = num - 1;
            }
        });

        if (zfbCount != 3) {
            return false;
        }

        return MJ.checkHuColorCards(MJ.ZI.HZ, MJ.ZI.BB, zfbCards);
    },
});